#include "mcu.h"

/*===================== GLOBAL VARIABLES DECLARATION ============================*/

uint32_t MCAL_Mcu_ClockGlobalStatus;
uint32_t MCAL_Mcu_LossOfLockCounter;
uint32_t MCAL_Mcu_BusFrequency;

/*===================== INTERNAL FUNCTION DECLARATION ===========================*/
/** System clock and PLL initialization */
void Mcu_PLL_Init(void);

/** Turn PLL ON */
void Mcu_PLL_ON(void);

/** Turn PLL OFF */
void Mcu_PLL_OFF(void);

/** Select PLL as clock source once it has been initialized */
void Mcu_SelectClockSource_PLL(void) ;

/** Select XTAL as clock source at any time */
void Mcu_SelectClockSource_XTAL(void);



/*======================== FUNCTION DEFINITIONS =================================*/

/*********************************************************************************
*	Name: Mcu_Init                                                                
*	Type: void                                                                    
*	Parameters: None                                                              
*	Description: init several configuration as MMCV and PLL clock                 
**********************************************************************************/
void Mcu_Init(void){
	/*initialization for the PLL module*/
	Mcu_PLL_Init(); 
	
}

/*********************************************************************************
*	Name: Mcu_InitClock                                                              
*	Type: void                                                                    
*	Parameters: None                                                              
*	Description: This function will init the clock of PLL.              
**********************************************************************************/
void Mcu_InitClock(void){
    Mcu_SelectClockSource_PLL();
	
}

/*********************************************************************************
*	Name: Mcu_DistributePllClock        
*	Type: void                                                                    
*	Parameters: None                                                              
*	Description: init several configuration as MMCV and PLL clock                 
**********************************************************************************/
void Mcu_DistributePllClock(void){

	Mcu_SelectClockSource_XTAL();

	
}

/*********************************************************************************
*	Name: Mcu_DistributePllClock        
*	Type: void                                                                    
*	Parameters: None                                                              
*	Description: init several configuration as MMCV and PLL clock                 
**********************************************************************************/
void Mcu_PLL_Init(void)
{       
    /* Disable PLL */
    Mcu_PLL_OFF();           
       
    /* Set PLL synthesizer register */
    SYNR_SYNDIV = SYNR_VALUE;         
    /* Set PLL divider register */  
    REFDV_REFDIV = REFDV_VALUE;         
    /* Configure PLL filter for optimal stability and lock time */
    REFDV_REFFRQ = REFFRQ_VALUE;        
    /* Set Postdiv value,  */
    POSTDIV_POSTDIV = POSTDIV_VALUE;                
    /* Configure VCO gain for optimal stability and lock time */
    SYNR_VCOFRQ = VCOFRQ_VALUE;         
    /* Clock Monitor Enable. This is required to enter Self Clock Mode */
    PLLCTL_CME = 1u;                     
    /* Self Clock Mode Enable, If CME & SCME are both asserted and the Clock Monitor
    in the oscillator block detects a loss of clock, Self Clock Mode will be entred */
    PLLCTL_SCME = 1u;                    
    /* Clear Self Clock Mode Interrupt Flag */                                                                          
    CRGFLG_SCMIF = 1u;                   
    /* Interrupt will be requested whenever SCMIF(Self Clock Mode Interrupt Flag) is set */ 
    CRGINT_SCMIE = 1u;                    

    /* Enable PLL and wait for locking */
    Mcu_PLL_ON();                          
}

/*********************************************************************************
*	Name: Mcu_PLL_ON       
*	Type: void                                                                    
*	Parameters: None                                                              
*	Description: Set on the PLL module                 
**********************************************************************************/
void Mcu_PLL_ON(void)
{     
          /* PLL enabled */
          PLLCTL_PLLON = 1u;                   
          
          /* Initialize PLL Loss-of-clock event counter */    
          MCAL_Mcu_LossOfLockCounter = 0u;            
          /* Wait until the PLL is within the desired frequency */
          while(!CRGFLG_LOCK)
          {}
          /* Initialize Global status variable to default value */                                   
          MCAL_Mcu_ClockGlobalStatus = MCU_STATUS_PLL_OK;        
          /* Clear IPLL Lock Interrupt Flag */
          CRGFLG_LOCKIF = 1u;                  
          /* Interrupt will be requested whenever LOCKIF(IPLL Lock Interrupt Flag)is set */        
          CRGINT_LOCKIE = 1u;                                                             
}

/*********************************************************************************
*	Name: Mcu_PLL_OFF      
*	Type: void                                                                    
*	Parameters: None                                                              
*	Description: Turn OFF the PLL module                 
**********************************************************************************/

void Mcu_PLL_OFF(void)
{
        /* Disable the PLL */
        PLLCTL_PLLON = 0u;
        /* update global status variable */                                   
        MCAL_Mcu_ClockGlobalStatus= MCU_STATUS_PLL_OFF;
}

/*********************************************************************************
*	Name: Mcu_SelectClockSource_PLL      
*	Type: void                                                                    
*	Parameters: None                                                              
*	Description: Set The PLL as Clock Source                
**********************************************************************************/

void Mcu_SelectClockSource_PLL(void)
{
        /* Select PLL as clock source */
        CLKSEL_PLLSEL = 1u;
        /* update global status variable */                                   
        MCAL_Mcu_ClockGlobalStatus = MCU_STATUS_PLL_SELECTED;
        /* update bus frequency variable with PLL frequency value */
        MCAL_Mcu_BusFrequency = ACTUAL_BUS_FREQ;
    
}

/*********************************************************************************
*	Name: Mcu_SelectClockSource_XTAL      
*	Type: void                                                                    
*	Parameters: None                                                              
*	Description: Set The XTAL as Clock Source                
**********************************************************************************/

void Mcu_SelectClockSource_XTAL(void)
{
        /* Select XTAL as clock source */
        CLKSEL_PLLSEL = 0u;
        /* update global status variable */                                   
        MCAL_Mcu_ClockGlobalStatus = MCU_STATUS_XTAL_SELECTED;
        /* update bus frequency variable with XTAL frequency value */
        MCAL_Mcu_BusFrequency = ((uint32_t)XTAL_FREQ_KHZ*1000u);
    
}


#pragma CODE_SEG __NEAR_SEG NON_BANKED
void interrupt MCU_Clock_Monitor_Isr(void)
{    
        /* Verify that IPLL Lock Interrupt Flag caused the interrupt */
        if (CRGFLG_LOCKIF == 1u)
        {
            /* Clear IPLL Lock Interrupt Flag */  
            CRGFLG_LOCKIF = 1u;
            /* Update Loss-of-Lock event counter */
            MCAL_Mcu_LossOfLockCounter++;
            if (MCAL_Mcu_LossOfLockCounter >= 5u)
            {
                /* Set gu16ClockGlobalStatus to its appropriate status */
                MCAL_Mcu_ClockGlobalStatus = MCU_STATUS_PLL_LOCK_ERROR;
                /* Configure all I/O to their default values */
                
                /* If we reach Loss-of-Lock 5 consecutive times, get into an infinite loop */
                for (;;){}
            }
        }
        else
        {        
            /* Verify that Self Clock Mode Interrupt flag caused the interrupt */
            if (CRGFLG_SCMIF == 1u)
            {
                /* Clear Self Clock Mode Interrupt Flag */
                CRGFLG_SCMIF = 1u;
                /* Set gu16ClockGlobalStatus to its appropriate status */ 
                MCAL_Mcu_ClockGlobalStatus = MCU_STATUS_SCM_ERROR;        
                /* If we reach SCM condition, get into an infinite loop */
                for (;;){}                
            }
        } 

}
#pragma CODE_SEG DEFAULT   
